//---------------------------------------------------------------------------------
// Copyright (c) 2008 VoiceLynx Project
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//     1. The origin of this software must not be misrepresented; you must not
//        claim that you wrote the original software. If you use this software
//        in a product, an acknowledgment in the product documentation would be
//        appreciated but is not required.
//
//     2. Altered source versions must be plainly marked as such, and must not be
//        misrepresented as being the original software.
//
//     3. This notice may not be removed or altered from any source
//        distribution.
//---------------------------------------------------------------------------------

#ifndef __VLPacketLogic_h__
#define __VLPacketLogic_h__

#include "VLPacketTranslator.h"
#include "VLTypes.h"

class VLPacketLogic
{
public:
  VLPacketLogic();
  virtual ~VLPacketLogic();

  virtual void setPacketTranslator(VLPacketTranslator &translator);

  //
  // Called on init and deinit to set up packet handlers
  //
  virtual void configurePacketTypes(bool init) = 0;

  //
  // Local events that are called by core
  //
  virtual VLPeerPtr createPeer() = 0;
  virtual void onConnect(VLPeer *user) = 0;
  virtual void onDisconnect(VLPeer *user) = 0;

  virtual void process() { }

  virtual void onStartVoice() = 0;
  virtual void onStopVoice() = 0;
  virtual void onVoiceData(VLByteArrayPtr encodedData) = 0;

protected:
  void sendPacket(VLPeer *user, VLBasePacket &packet)
  { mPacketTranslator->sendPacket(user, packet); }

  void sendPacket(std::vector<VLPeer *> users, VLBasePacket &packet)
  { mPacketTranslator->sendPacket(users, packet); }

  void broadcastPacket(VLBasePacket &packet, VLPeer *exceptTo = 0)
  { mPacketTranslator->broadcastPacket(packet, exceptTo); }

  void disconnectFromPeer(VLPeer *peer, VLEDisconnectReason reason)
  { mPacketTranslator->disconnectFromPeer(peer, reason); }

  template <class OwnerT, class PacketT>
  void registerMessageHandler(VLEPacketType packetType, OwnerT* obj, void (OwnerT::*memFn)(VLPeer *, PacketT &))
  { mPacketTranslator->registerMessageHandler(packetType, obj, memFn); }

  void unregisterMessageHandler(VLEPacketType packetType)
  { mPacketTranslator->unregisterMessageHandler(packetType); }

protected:
  VLPacketTranslator *mPacketTranslator;
};

typedef std::auto_ptr<VLPacketLogic> VLPacketLogicPtr;

class VLClientPacketLogic : public VLPacketLogic
{
public:
  VLClientPacketLogic();

  void configurePacketTypes(bool init);

  void setUsername(const VLString &username) { mUsername = username; }
  void setPassword(const VLString &password) { mPassword = password; }

  virtual VLPeerPtr createPeer();
  virtual void onConnect(VLPeer *user);
  virtual void onDisconnect(VLPeer *user);

  virtual void onStartVoice();
  virtual void onStopVoice();
  virtual void onVoiceData(VLByteArrayPtr encodedData);

  virtual void onReceiveAuthenticationResponse  
                                        ( VLPeer *peer, VLAuthenticationResponsePacket &packet );
  virtual void onReceiveStartVoice          ( VLPeer *peer, VLStartVoicePacket &packet         );
  virtual void onReceiveStopVoice           ( VLPeer *peer, VLStopVoicePacket &packet          ); 
  virtual void onReceiveVoiceData           ( VLPeer *peer, VLVoiceDataPacket &packet          );
  virtual void onReceiveUserJoined          ( VLPeer *peer, VLUserJoinedPacket &packet         );
  virtual void onReceiveUserLeft            ( VLPeer *peer, VLUserLeftPacket &packet           );
  virtual void onReceiveUserChangedChannel  ( VLPeer *peer, VLUserChangedChannelPacket &packet );
  virtual void onReceiveChannelState        ( VLPeer *peer, VLChannelStatePacket &packet       );

  const VLUserIdToUserMap &getUsers() { return mUsers; }

private:
  VLPeer *mPeer;

  VLUserIdToUserMap mUsers;

  VLString mUsername;
  VLString mPassword;
};

class VLServerPacketLogic : public VLPacketLogic
{
public:
  // init functions
  VLServerPacketLogic();
  void configurePacketTypes(bool init);

  // Called by core
  virtual VLPeerPtr createPeer();
  virtual void onConnect(VLPeer *user);
  virtual void onDisconnect(VLPeer *user);

  virtual void onStartVoice();
  virtual void onStopVoice();
  virtual void onVoiceData(VLByteArrayPtr encodedData);

  virtual void process();

  // On receiving packets
  virtual void onReceiveStartVoice        ( VLPeer *peer, VLStartVoicePacket &packet     );
  virtual void onReceiveStopVoice         ( VLPeer *peer, VLStopVoicePacket &packet      ); 
  virtual void onReceiveVoiceData         ( VLPeer *peer, VLVoiceDataPacket &packet      );
  virtual void onReceiveAuthentication    ( VLPeer *peer, VLAuthenticationPacket &packet );
  virtual void onReceiveChannelStateRequest
                                          ( VLPeer *peer, VLChannelStateRequestPacket &packet );                                               

  // "Hooks" for people extending this class to modify functionality
  virtual bool authenticateUser(VLAuthenticationPacket &packet);

  // Custom methods that won't be extended often
  void disconnectUser(VLUser *user, VLEDisconnectReason reason);

private:
  
  VLUserId mNextUserId;

  VLUserList mUsers;
  
};


#endif
